package com.JFapp.service.impl;

import com.JFapp.constants.SystemConstants;
import com.JFapp.domain.entity.Menu;
import com.JFapp.domain.entity.ResponseResult;
import com.JFapp.domain.vo.MenuRoleIdsVo;
import com.JFapp.domain.vo.RoleMenuVO;
import com.JFapp.eumns.AppHttpCodeEnum;
import com.JFapp.exception.SystemException;
import com.JFapp.mapper.MenuMapper;
import com.JFapp.service.MenuService;
import com.JFapp.utils.SecurityUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.swagger.annotations.ApiOperation;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 菜单权限表(Menu)表服务实现类
 *
 * @author makejava
 * @since 2024-02-11 22:14:35
 */
@Service("menuService")
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    @Override
    @ApiOperation("查询菜单权限")
    public List<String> selectPermByUserId(Long id) {
        //判断角色，赋予权限
        //如果是超级管理员返回所有权限
        if(SecurityUtils.isAdmin()){
            LambdaQueryWrapper<Menu> wrapper=new LambdaQueryWrapper<>();
            wrapper.in(Menu::getMenuType, SystemConstants.MENU, SystemConstants.BUTTON);
            wrapper.eq(Menu::getStatus,SystemConstants.STATUS_NORMAL);
            List<Menu> menus = list(wrapper);
            List<String> perms = menus.stream()
                    .map(Menu::getPerms)
                    .collect(Collectors.toList());
            return perms;
        }
        //否则根据id返回对应权限
        return getBaseMapper().selectPermsById(id);
    }

    @Override
    @ApiOperation("搜索菜单")
    public List<Menu> selectRoutersMenuTreeByUserId(Long userId) {
        MenuMapper menuMapper=getBaseMapper();
        List<Menu> menus=null;
        //判断角色是否为超级管理员，是则返回所有菜单栏目;否则返回对应菜单栏目
        if(SecurityUtils.isAdmin()){
            menus= menuMapper.selectAllRouterMenu();
        }else {
            menus=menuMapper.selectRouterMenuTreeByUserId(userId);
        }
        //构建tree
        //找出第一层菜单，再将对应子属性设置到children属性中
        List<Menu> menusTree=builderMenuTree(menus,0L);
        return menusTree;
    }

    private List<Menu> getChildren(Long id) {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<Menu> wrapper = queryWrapper.select().eq(Menu::getParentId, id)
                .orderByAsc(Menu::getOrderNum,Menu::getStatus,Menu::getVisible);
        List<Menu> childenList = baseMapper.selectList(wrapper);
        return childenList;
    }

    @Override
    public ResponseResult changeMenuStatus(Long menuId, String status) {
        LambdaUpdateWrapper<Menu> updateWrapper=new LambdaUpdateWrapper<>();
        LambdaUpdateWrapper<Menu> wrapper = updateWrapper.set(Menu::getStatus, status).eq(Menu::getId, menuId);
        update(wrapper);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult getMenuById(Long menuId) {
        Menu menu = baseMapper.selectById(menuId);
        return ResponseResult.okResult(menu);
    }

    @Override
    public ResponseResult getMenuList(String status, String menuName) {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(Objects.nonNull(menuName), Menu::getMenuName, menuName);
        queryWrapper.eq(Objects.nonNull(status),Menu::getStatus,status);
        queryWrapper.orderByAsc(Menu::getId,Menu::getOrderNum);
        List<Menu> menuList = list(queryWrapper);
        return ResponseResult.okResult(menuList);
    }

    @Override
    public ResponseResult getMenuTreeList() {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Menu::getStatus,SystemConstants.Menu_Status_Normal)
                .orderByDesc(Menu::getId,Menu::getOrderNum);
        List<Menu> menuLists = list(queryWrapper);
        List<RoleMenuVO>  roleMenuVOS =  menuLists.stream()
                .map(menu -> {
                    RoleMenuVO roleMenuVO = new RoleMenuVO();
                    roleMenuVO.setId(menu.getId());
                    roleMenuVO.setLabel(menu.getMenuName());
                    roleMenuVO.setParentId(menu.getParentId());
                    return roleMenuVO;
                })
                .collect(Collectors.toList());

        List<RoleMenuVO> menuTree = roleBuilderMenuTree(roleMenuVOS,0L);
        return ResponseResult.okResult(menuTree);
    }

    @Override
    public ResponseResult getRoleMenuTreeById(Long id) {
        MenuMapper menuMapper = getBaseMapper();
        List<Long> longs = menuMapper.selectMenuIdByUserId(id);
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Menu::getStatus,SystemConstants.Menu_Status_Normal);
        queryWrapper.orderByDesc(Menu::getId,Menu::getOrderNum);
        List<Menu> menuList = list(queryWrapper);
        List<RoleMenuVO>  menus =  menuList.stream()
                .map(menu -> {
                    RoleMenuVO roleMenuVO = new RoleMenuVO();
                    roleMenuVO.setId(menu.getId());
                    roleMenuVO.setLabel(menu.getMenuName());
                    roleMenuVO.setParentId(menu.getParentId());
                    return roleMenuVO;
                })
                .collect(Collectors.toList());
        //构建菜单tree

        List<RoleMenuVO> menuTree = roleBuilderMenuTree(menus,0L);
        MenuRoleIdsVo menuRoleIdsVo = new MenuRoleIdsVo(menuTree,longs);
        return ResponseResult.okResult(menuRoleIdsVo);
    }

    public ResponseResult addMenu(Menu menu) {
        save(menu);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult deleteMenu(Long menuId) {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(Menu::getParentId,menuId);
        long count = count(queryWrapper);
        if(count > 0){
            return  ResponseResult.errorResult(AppHttpCodeEnum.HAS_CHILD_MENU);
        }
        removeById(menuId);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult updateMenu(Menu menu) {
        if(menu.getParentId().equals(menu.getId())){
            return  ResponseResult.errorResult(AppHttpCodeEnum.PARENT_MENU_ERROR);
        }
        updateById(menu);
        return ResponseResult.okResult();
    }

    private List<RoleMenuVO> roleBuilderMenuTree(List<RoleMenuVO> roleMenuVOList, long parentId ) {
        List<RoleMenuVO> menuTree = roleMenuVOList.stream()
                .filter(roleMenuVo -> roleMenuVo.getParentId().equals(parentId))
                .map(roleMenuVo -> roleMenuVo.setChildren(roleGetChildren(roleMenuVo,roleMenuVOList)))
                .collect(Collectors.toList());
        return menuTree;

    }

    private List<RoleMenuVO> roleGetChildren(RoleMenuVO roleMenuVO, List<RoleMenuVO> roleMenuVOS) {
        List<RoleMenuVO> childrenList = roleMenuVOS.stream()
                .filter(m -> m.getParentId().equals(roleMenuVO.getId()))
                .map(m->m.setChildren(roleGetChildren(m,roleMenuVOS)))
                .collect(Collectors.toList());
        return childrenList;
    }


    private List<Menu> builderMenuTree(List<Menu> menus, Long parentId) {
        List<Menu> menuTree = menus.stream()
                .filter(Menu -> Menu.getParentId().equals(parentId))
                .map(menu->menu.setChildren(getChildren(menu, menus)))
                .collect(Collectors.toList());
        return menuTree;
    }


    private List<Menu> getChildren(Menu menu, List<Menu> menus) {
        List<Menu> childrenList = menus.stream()
                .filter(m -> m.getParentId().equals(menu.getId()))
                .map(m->m.setChildren(getChildren(m,menus)))
                .collect(Collectors.toList());
        return childrenList;
    }
}
